package binary

import (
	"bytes"
	"encoding/binary"
	"errors"
	"io"
)

// MessageType 消息类型
type MessageType byte

const (
	// UnknownMessage 未知消息类型
	UnknownMessage MessageType = iota
	// TextMessage 文本消息
	TextMessage
	// SubscribeMessage 订阅消息
	SubscribeMessage
	// UnsubscribeMessage 取消订阅消息
	UnsubscribeMessage
	// PingMessage 心跳请求消息
	PingMessage
	// PongMessage 心跳响应消息
	PongMessage
)

// Message 二进制消息结构
type Message struct {
	// 消息类型
	Type MessageType
	// 消息内容
	Content string
	// 主题（用于订阅/取消订阅）
	Topic string
}

// Encode 将消息编码为二进制格式
// 格式：
// - 1字节: 消息类型
// - 4字节: 内容长度
// - N字节: 内容
// - 4字节: 主题长度
// - M字节: 主题
func (m *Message) Encode() ([]byte, error) {
	buf := new(bytes.Buffer)

	// 写入消息类型
	if err := buf.WriteByte(byte(m.Type)); err != nil {
		return nil, err
	}

	// 写入内容长度和内容
	contentBytes := []byte(m.Content)
	if err := binary.Write(buf, binary.LittleEndian, uint32(len(contentBytes))); err != nil {
		return nil, err
	}
	if _, err := buf.Write(contentBytes); err != nil {
		return nil, err
	}

	// 写入主题长度和主题
	topicBytes := []byte(m.Topic)
	if err := binary.Write(buf, binary.LittleEndian, uint32(len(topicBytes))); err != nil {
		return nil, err
	}
	if _, err := buf.Write(topicBytes); err != nil {
		return nil, err
	}

	return buf.Bytes(), nil
}

// Decode 从二进制数据解码消息
func Decode(data []byte) (*Message, error) {
	buf := bytes.NewReader(data)

	// 读取消息类型
	typeByte, err := buf.ReadByte()
	if err != nil {
		return nil, err
	}

	msg := &Message{
		Type: MessageType(typeByte),
	}

	// 读取内容长度
	var contentLen uint32
	if err := binary.Read(buf, binary.LittleEndian, &contentLen); err != nil {
		return nil, err
	}

	// 读取内容
	contentBytes := make([]byte, contentLen)
	if _, err := io.ReadFull(buf, contentBytes); err != nil {
		return nil, err
	}
	msg.Content = string(contentBytes)

	// 读取主题长度
	var topicLen uint32
	if err := binary.Read(buf, binary.LittleEndian, &topicLen); err != nil {
		return nil, err
	}

	// 读取主题
	topicBytes := make([]byte, topicLen)
	if _, err := io.ReadFull(buf, topicBytes); err != nil {
		return nil, err
	}
	msg.Topic = string(topicBytes)

	return msg, nil
}

// TryDecode 尝试解码二进制消息，如果失败则返回nil和错误
func TryDecode(data []byte) (*Message, error) {
	if len(data) < 5 { // 至少需要1字节类型 + 4字节内容长度
		return nil, errors.New("message too short")
	}
	return Decode(data)
}

// NewTextMessage 创建一个文本消息
func NewTextMessage(content string) *Message {
	return &Message{
		Type:    TextMessage,
		Content: content,
	}
}

// NewSubscribeMessage 创建一个订阅消息
func NewSubscribeMessage(topic string) *Message {
	return &Message{
		Type:  SubscribeMessage,
		Topic: topic,
	}
}

// NewUnsubscribeMessage 创建一个取消订阅消息
func NewUnsubscribeMessage(topic string) *Message {
	return &Message{
		Type:  UnsubscribeMessage,
		Topic: topic,
	}
}

// NewPingMessage 创建一个心跳请求消息
func NewPingMessage() *Message {
	return &Message{
		Type: PingMessage,
	}
}

// NewPongMessage 创建一个心跳响应消息
func NewPongMessage() *Message {
	return &Message{
		Type: PongMessage,
	}
}
